package tv.geir.slackspace.common;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import tv.geir.slackspace.code.ClassLoadingObjectInputStream;
import tv.geir.slackspace.code.ProminentClassLoader;


/**
 * 
 * Use this class to serialize and deserialize objects where errors regarding
 * serialization (that be classloader exceptions, etc) should be ignored. 
 * If (de)serializing fails, exceptions are swallowed and if dezerialiazation
 * fails, <code>null</code> is returned.
 *  
 * @author Geir Gullestad Pettersen
 *
 */
public class ObjectSerializer {

	/**
	 * Returns a byte-array representation of the object
	 * 
	 * @param s object to serialize
	 * @return byte array
	 */
	public byte[] serialize(Object s) {
		if (s == null) {
			return null;
		}

		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			ObjectOutputStream oos = new ObjectOutputStream(out);
			oos.writeObject(s);
			oos.close();

			return out.toByteArray();
		} catch (Throwable e) {
			throw new SlackSpaceException("Error serializing object: "
					+ e.getMessage(), e);
		}
	}
	
	/**
	 * Deserializes the byte array into an object instance.
	 * 
	 * @param bytes a serialized object
	 * @return dedesialized object
	 * @throws SlackSpaceException if deserialization for some reason fails
	 */
	public Object deserialize( byte[] bytes ) {
        // FIX  get classloader from somwhere, don't use default. 
		return deserialize( bytes, getClass().getClassLoader() );
	}
	
	/**
	 * Deserializes the byte array into an object instance.
	 * 
	 * @param bytes a serialized object
	 * @return deserialized object
	 * @throws SlackSpaceException if deserialization for some reason fails
	 */
	public Object deserialize( byte[] bytes , ClassLoader cl) {
		if( bytes == null ) {
			return null;
		}
		ByteArrayInputStream in = new ByteArrayInputStream( bytes );
		try {
			
			ObjectInputStream ois = new ClassLoadingObjectInputStream( cl, in );
			return (Serializable) ois.readObject();
		} catch (ClassCastException ce) {
			throw new SlackSpaceException( "Error deserializing object of type: " + ce.getMessage(), ce );
		} catch( Throwable t ) {
			throw new SlackSpaceException( "Error deserializing object: " + t.getMessage(), t );
		}
		
	}
	
	
}
